home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Applications / Alpha.5.96 folder / Tcl / SystemCode / procs.tcl < prev    next >
Encoding:
Text File  |  1994-09-20  |  16.1 KB  |  669 lines  |  [TEXT/ALFA]

  1. #==============================================================================
  2. proc normalLeftBracket {} {
  3.     insertText "\{"
  4. }
  5. proc normalRightBracket {} {
  6.     insertText "\}"
  7. }
  8. bind '\[' <zs>  normalLeftBracket
  9. bind '\]' <zs>  normalRightBracket
  10.             
  11. # Select the next or current word. If word already selected, will go to next.
  12. proc hiliteWord {} {
  13.     if {[getPos]!=[selEnd]}    forwardChar
  14.     forwardWord
  15.     set start [getPos]
  16.     backwardWord
  17.     select $start [getPos]
  18. }
  19.  
  20. bind 'h' <z> hiliteWord
  21.  
  22. #================================================================================
  23. # Mode variables
  24. #================================================================================
  25. # For mark stack.
  26. set markName 0
  27. set markStack ""
  28.  
  29. # mapping of windows to current modes.
  30. set winModes("") ""
  31.  
  32. # making vars local to windows
  33. # 'incomingVars' used to hold old var values that have been overwritten in current window
  34.  
  35. #================================================================================
  36. # Handle 'flag' and 'var' menu selections.
  37. #================================================================================
  38. proc editFlag {menu item} {
  39.     global $item incomingVars localVars modifiedVars
  40.  
  41.     lappend modifiedVars $item
  42.     set val [expr ([set $item]-1)*-1]
  43.     markMenuItem $menu $item [expr ($val)?"on":"off"]
  44.     set $item $val
  45.  
  46. }
  47.  
  48. proc editVar {menu item} {
  49.     global $item incomingVars localVars modifiedVars
  50.  
  51.     lappend modifiedVars $item
  52.     append prmpt "New Value of " $item ": "
  53.     if ![catch {prompt $prmpt [set $item]} res] {
  54.         set $item $res
  55.     }
  56. }
  57.  
  58.  
  59.  
  60.  
  61. #================================================================================
  62.  
  63. # Instantiate a global variable to the path of a file (usually an app). As a
  64. # side-effect, make the instantiation permanent by adding a line to 'definitions.tcl'.
  65. proc addAppPath {name var} {
  66.     global $var
  67.     
  68.     if {[catch {getfile "Find '$name' app:"} path]} {return 1}
  69.     set $var $path
  70.  
  71.     addUserLine "set $var \"[quoteExpr2 $path]\""
  72.     return 0
  73. }
  74.  
  75. proc addUserLine {line} {
  76.     global HOME
  77.  
  78.     if {[file exists "$HOME:userStartup.tcl"]} {
  79.         set fid [open "$HOME:userStartup.tcl" "a"]
  80.     } else {
  81.         set fid [open "$HOME:userStartup.tcl" "w"]
  82.     }
  83.     puts $fid $line
  84.     close $fid
  85. }
  86.  
  87.  
  88. proc addAlphabitsLine {line} {
  89.     global HOME
  90.  
  91.     set fid [open "$HOME:Tcl:SystemCode:AlphaBits.tcl" "a"]
  92.     puts $fid $line
  93.     close $fid
  94. }
  95.  
  96.  
  97. proc getFileSig {f} {
  98.     catch {lindex [ls -l $f] 6} var
  99.     return $var
  100. }
  101.  
  102.  
  103. # Look for given app sig in active processes. If not there, try to 
  104. # launch with 'path' prompting for 'path' if necessary.
  105. # Return the real name of the app. Don't switch.
  106. proc checkRunning {name sig path} {
  107.     global $path
  108.     foreach proc [processes] {
  109.         if {[lindex $proc 1] == $sig} {
  110.             return [lindex $proc 0]
  111.         }
  112.     }
  113.     if {![info exists $path] || ![file exists [set $path]]} {
  114.         if {[addAppPath $name $path]} return
  115.     }
  116.     if {[catch {getFileSig [set $path]}]} {
  117.         if {[addAppPath $name $path]} return
  118.     }
  119.     set sig [getFileSig [set $path]]
  120.     if {[catch {launch -f [set $path]}]} {
  121.         error "Problem with launching file (out of memory?)"
  122.     }
  123.     return [file tail [set $path]]
  124. #    return [checkRunning $name $sig $path]
  125. }
  126.  
  127. #================================================================================
  128. # Excalibur is the only Mac spell-checker that I know of which will handle LaTeX as
  129. # well as ordinary text.
  130.  
  131.  
  132. proc spellcheckWindow {} {
  133.     global excaliburPath resumeRevert
  134.  
  135.     catch {checkRunning Excalibur XCLB excaliburPath} name
  136.  
  137.     if {[winInfo dirty]} {
  138.         if {[askyesno "Save '[lindex [winNames] 0]'?"] == "yes"} {
  139.             save
  140.         }
  141.     }
  142.     if {[catch {sendOpenEvent -n $name [lindex [winNames -f] 0]}] } {
  143.         beep 
  144.     } else {
  145.         switchTo $name
  146.     }
  147.     set resumeRevert 1
  148. }
  149.  
  150. proc spellcheckSelection {} {
  151.     global excaliburPath 
  152.  
  153.     catch {checkRunning Excalibur XCLB excaliburPath} name
  154.  
  155.     if {[getPos] == [selEnd]} {
  156.         beep
  157.         message "No selection"
  158.         return;
  159.     }
  160.     copy
  161.     switchTo $name
  162. }
  163.  
  164. #================================================================================
  165.  
  166.  
  167. proc alphaHelp {} {
  168.     global HOME winModes
  169.     edit -r "$HOME:Help:Intro"
  170. }
  171.  
  172.  
  173. proc tclHelp {} {
  174.     global HOME
  175.     edit -r "$HOME:Help:Tcl Commands"
  176. }
  177.  
  178.  
  179. set patternLibrary {
  180.     { "Pascal to C Comments" {        \{([^\}]*)\}} {/* \1 */} }
  181.     { "C++ to C Comments" {//(.*)} {/* \1 */}}
  182. }
  183.  
  184.  
  185. proc dividingLine {} {
  186.     insertText "================================================================================\r"
  187. }
  188. bind 'l' <C> dividingLine
  189.  
  190. proc texDividingLine {} {
  191.     insertText "%================================================================================\r"
  192. }
  193. bind 'l' <C> texDividingLine TeX
  194.  
  195. proc cDividingLine {} {
  196.     insertText "//================================================================================\r"
  197. }
  198. bind 'l' <C> cDividingLine C
  199. bind 'l' <C> cDividingLine C++
  200.  
  201. proc tclDividingLine {} {
  202.     insertText "#================================================================================\r"
  203. }
  204. bind 'l' <C> tclDividingLine Tcl
  205.  
  206.  
  207. #================================================================================
  208.  
  209. if {![string length [info commands oldCd]]} {
  210.     rename cd oldCd
  211. }
  212.  
  213. proc cd args {
  214.     global HOME
  215.     if {[llength $args]} {
  216.         oldCd [string trim [eval list $args] "        \{\}"]
  217.     } else {
  218.         oldCd $HOME
  219.     }
  220. }
  221.  
  222.  
  223.  
  224. #############################################################################
  225. #  List the name and value of each element of the array $arrName.
  226. #  (Convenient to use as a shell command.)
  227. #
  228. #  Note: it's slower to insert the lines one-by-one like this, but 
  229. #  assembling everything in $lines before inserting can seriously crash Alpha
  230. #  if the result is too big.  (Trying to list the contents of $auto_index()
  231. #  will do it.)  This method seems to be more robust.
  232. #
  233. proc listArray {arrName} {
  234.     global $arrName
  235.     set lines {}
  236.     if {![catch {info vars $arrName}]} {
  237.         foreach nm [array names $arrName] {
  238.             set val [expr \$$arrName\($nm\)]
  239.             append lines "\r\"$nm\"\t\{$val\}"
  240.         }
  241.         insertText $lines
  242.     } else {
  243.         alertnote "\"$arrName\" doesn't exist in this context"
  244.     }
  245. }
  246.  
  247.  
  248.  
  249. #================================================================================
  250.     
  251. proc selectParagraph {} {
  252.     set pos [getPos]
  253.     set start [paraStart $pos] 
  254.     set finish [paraFinish $pos]
  255.     goto $start
  256.     select $start $finish
  257. }
  258.  
  259. # wrapText ==  getText ; breakIntoLines ; replaceText
  260. # Remove text from window, transform (join, del-ws), insert back into window.
  261. proc fillTextByPar {from to} {
  262.     set text [getText $from $to]
  263.     regsub -all "\r(\[ \t\]*\r)+" $text "\r\r\r" text
  264.     regsub -all "(\[^\r\])\r" $text "\\1 " text
  265.     regsub -all "\[ \t\]+" $text " " text
  266.     return [breakIntoLines $text]
  267. }
  268.  
  269. proc fillRegionByPar {{start -1} {finish -1}} {
  270. #    # if {[getPos] == [selEnd]} { return}
  271.     if {($start < 0) || ($finish < 0)} {
  272.         set start [lineStart [getPos]]
  273.         set finish [selEnd] }
  274.     if {$start >= $finish} return
  275.     goto $start
  276.     set text [fillTextByPar $start $finish]
  277.     replaceText $start $finish $text "\r"
  278. }
  279.     
  280. #
  281. # join Lines in region -- if no optional args, use selection
  282. #
  283. proc joinRegion {{from -1} {to -1}} {
  284.     if {($from < 0) || ($to < 0)} {    set from [getPos] ; set to [selEnd] }
  285.     if {$from >= $to} return
  286.     set text [getText $from $to]
  287.     regsub -all "\r(\[ \t\]*\r)+" $text "\r\r\r" text
  288.     regsub -all "(\[^\r\])\r" $text "\\1 " text
  289.     replaceText $from $to $text "\r"
  290. }
  291. # WARNING:    regsub ^$ refers to string endpts (not lines)
  292. # FUTURE:    filterLines like perl:
  293. #    replaceText[apply_to_all(cmd,split [getText [getPos] [selEnd]] "\r")]
  294. # OR:    replaceInRegion: dup_\r, $=>\r ??
  295. #
  296.  
  297.  
  298. #
  299. # Remove text from window, transform (delete dup ws), insert back into window.
  300. #
  301. # inputs: message, alertnote, askyesno, listpick, prompt KILLS SELECTION.
  302. # search: bnds = search -forward -regExpr -ignoreCase -matchWords -noabort 
  303. #        -l limit pat pos
  304. proc regsubInRegion {from to srch repl} {
  305.     if {![string length $srch]} return
  306.     if {$from >= $to} return
  307.     set text [getText $from $to]
  308.     regsub -all "$srch" $text "$repl" text
  309.     replaceText $from $to $text
  310. }
  311. #    while {($pos < $to) &&
  312. #          ![catch {search -f 1 -r 1 -i 1 -m 0 "$srch" $pos} mtch]} {
  313. #        set mbeg [lindex $mtch 0]
  314. #        set pos [lindex $mtch 1]
  315. #        replaceText $mbeg $pos $repl }
  316.  
  317. #proc backSlashSub {arg} { eval [concat return "\"$arg\""] }
  318.  
  319. proc backSlashSub {arg} {
  320.     regsub -all {\\} $arg {\\\\} arg
  321.     regsub -all {\[} $arg {\\[} arg
  322.     regsub -all {\]} $arg {\\]} arg
  323.     eval [concat return "\"$arg\""]
  324. }
  325.  
  326. proc replaceInRegion {} {
  327.     if [catch {prompt "Search RegExpr:" ""} srch] return
  328.     if [catch {prompt "Replace String:" ""} repl] return
  329.     if {![string length $srch]} return
  330.     regsubInRegion [getPos] [selEnd] \
  331.         [backSlashSub "$srch"] [backSlashSub "$repl"]
  332. }
  333.  
  334. #
  335. # Apply command to each line (or paragraph) in selection ;
  336. #    if no cmd arg then prompts for it
  337. #
  338. proc filterLines {{cmd 0} {parunit 0}} {
  339.     if {$cmd == 0} {
  340.       if {[catch { prompt "Line-filter command: " "" } cmd]} { return } }
  341.     if {![string length $cmd]} return
  342.     set unitStart lineStart
  343.     set unitEnd nextLineStart
  344.     if {$parunit} {
  345.         set unitStart paraStart
  346.         set unitEnd paraFinish }
  347.     set pos [$unitStart [getPos]]
  348.     set finish [selEnd]
  349.     if {$pos >= $finish} return
  350.     goto $pos
  351.     createTMark "filterLend" $finish
  352.     set next [$unitEnd $pos]
  353.     while {(($next > $pos) && ($pos < $finish))} {
  354.         goto [expr $next-1]
  355.         createTMark "filterLnext" $next
  356.         setMark
  357.         goto $pos
  358.         markHilite
  359.         if {[catch [list uplevel #0 "$cmd"] retval]} {
  360.             select $pos $finish
  361.             alertnote $retval
  362.             return
  363.         }
  364.         if {$next==$finish} break
  365.         set ind [lsearch -regexp [lindex [getTMarks] 0] "filterLend.*"]
  366.         set finish [lindex [lindex [lindex [getTMarks] 0] $ind] 2]
  367.         gotoTMark "filterLnext"
  368.         set pos [$unitStart [getPos]]
  369.         set next [$unitEnd $pos]
  370.     }
  371.     removeTMark "filterLend"
  372.     removeTMark "filterLnext"
  373. }
  374.  
  375.  
  376. proc filterParagraphs {{cmd 0}} { filterLines $cmd 1 }
  377.  
  378. # WARNING: deselecting sets the mark to selEnd
  379. proc sortParagraphs {{from -1} {to -1}} {
  380.     if {($from < 0) || ($to < 0)} {    set from [getPos] ; set to [selEnd] }
  381.     if {$from >= $to} return
  382.     joinRegion {$from $to}
  383.     select [getPos] [nextLineStart [getMark]]
  384.     sortLines
  385.     select [getPos] [getPos]
  386.     regsubInRegion [getPos] [getMark] "\r" "\r\r" 
  387.     wrapRegion
  388. }
  389.  
  390. #
  391. # Sample
  392. #
  393. proc filterRegion {{from -1} {to -1} {cmd 0} {newwin 0}} {
  394.     if {$cmd == 0} {
  395.       if {[catch { prompt "Eval command: " "" } cmd]} { return }
  396.     }
  397.     if {![string length $cmd]} return
  398.     if {($from < 0) || ($to < 0)} {    set from [getPos] ; set to [selEnd] }
  399.     if {$from >= $to} return
  400.     set pos [getPos]
  401.     set text [getText $from $to]
  402.     set text [$cmd $text]
  403.     replaceText $from $to $text "\r"
  404.     goto $pos
  405. }
  406.  
  407.  
  408. #
  409. set lastEvaled ""
  410. proc evaluate {} {
  411.     global lastEvaled
  412.     if {[string length $lastEvaled]} {
  413.         set p "M-x ($lastEvaled): "
  414.     } else {
  415.         set p "M-x: "
  416.     }
  417.     if {[catch {statusPrompt $p} text]} {return}
  418.     if {![string length $text]} {set text $lastEvaled}
  419.     $text
  420.     set lastEvaled $text
  421. }
  422.  
  423.  
  424. # First, define macros to bypass the electric braces.
  425. proc ordLeftBrace {} {
  426.     insertText "        \{"
  427. }
  428. bind {'['} <cs> ordLeftBrace
  429.  
  430. proc ordRightBrace {} {
  431.     insertText "\}"
  432.     blink [matchIt "\}" [expr [getPos]-1]]
  433. }
  434. bind {']'} <cs> ordRightBrace
  435.     
  436. proc quoteWord {} {
  437.     backwardWord
  438.     insertText "'"
  439.     forwardWord
  440.     insertText "'"
  441. }
  442. bind ''' <z> quoteWord
  443.  
  444. #================================================================================
  445.  
  446. proc tomac {fname} {
  447.     set fd [open $fname "r"]
  448.     set text [read $fd]
  449.     close $fd
  450.     set fd [open $fname "w"]
  451.     regsub "\n" $text "\r" text
  452.     puts -nonewline $fd $text
  453.     close $fd
  454. }
  455.  
  456. proc tounix {fname} {
  457.     set fd [open $fname "r"]
  458.     set text [read $fd]
  459.     close $fd
  460.     set fd [open $fname "w"]
  461.     regsub "\r" $text "\n" text
  462.     puts -nonewline $fd $text
  463.     close $fd
  464. }
  465.  
  466.  
  467. proc cat args {
  468.     set files ""
  469.     foreach a $args {
  470.         foreach f [glob $a] {
  471.             lappend files $f
  472.         }
  473.     }
  474.     foreach f $files {
  475.         append text "==============<$f>==============\r"
  476.         set fd [open $f "r"]
  477.         append text "[read $fd]\r\r"
  478.         close $fd
  479.     }
  480.     return $text
  481. }
  482.  
  483. proc catto args {
  484.     set len [llength $args]
  485.     set to [lindex $args [expr $len -1]]
  486.     set args [lrange $args 0 [expr $len -2]]
  487.  
  488.     set files ""
  489.     foreach a $args {
  490.         foreach f [glob $a] {
  491.             lappend files $f
  492.         }
  493.     }
  494.     foreach f $files {
  495.         append text "==============<$f>==============\r"
  496.         set fd [open $f "r"]
  497.         append text "[read $fd]\r\r"
  498.         close $fd
  499.     }
  500.  
  501.     set dfile $to
  502.     if {[file exists $dfile]} {
  503.         set fid [open $dfile "a"]
  504.     } else {
  505.         set fid [open $dfile "w"]
  506.     }
  507.     puts $fid $text
  508.     close $fid
  509. }
  510.  
  511.  
  512. ##############################################################################
  513. #  To be used in the windows created by "matchingLines" or by batch searches.
  514. #
  515. #  With the cursor positioned in a line corrsponding to a match, 
  516. #  go back and select the line in the original file that 
  517. #  generated this match.  (Like emacs 'Occur' functionality)
  518. #
  519. proc gotoMatch {} {
  520.     set text [getText [lineStart [getPos]] [expr [nextLineStart [getPos]] - 1]]
  521.     set ind1 [string first "∞" $text]
  522.     set ind2 [string last "∞" $text]
  523.     if {$ind1 == $ind2} {
  524.         set fname [string trim [string range $text $ind1 end] {∞}]
  525.         set msg ""
  526.     } else {
  527.         set fname [string trim [string range $text $ind1 $ind2] {∞}]
  528.         set msg [string trim [string range $text $ind2 end] {∞}]
  529.     }
  530.     if {[expr {[lsearch [winNames -f] "*$fname"] >= 0}]} {
  531.         bringToFront $fname
  532.     } elseif {[file exists $fname]} {
  533.         edit $fname
  534.     } else {
  535.         alertnote "File \" $fname \" not found." ; return
  536.     }
  537.     if {![regexp {Line ([0-9]+):} $text dummy line]} { error "Garbage" }
  538.     goto [rowColToPos $line 0]
  539.     message $msg
  540. }
  541. bind 'c' <Cz>        gotoMatch
  542.  
  543.  
  544. #================================================================================
  545.  
  546. proc prevIntro {} {
  547.     set res [search -f 0 -r 0 {== } [getPos]]
  548.     display [lineStart [expr [lineStart [lindex $res 0]] - 1]]
  549. }
  550.  
  551. proc nextIntro {} {
  552.     set res [search -f 1 -r 0 {== } [getPos]]
  553.     set res [lindex $res 1]
  554.     set res [search -f 1 -r 0 {== } $res]
  555.     display [lineStart [expr [lineStart [lindex $res 0]] - 1]]
  556. }
  557.  
  558. #================================================================================
  559.  
  560. proc searchStart {} {
  561.     global search_start
  562.     select [getPos]
  563.     setMark
  564.     if {[catch {goto $search_start}]} {message "No previous search"}
  565. }
  566.  
  567. #================================================================================
  568.  
  569.  
  570. proc listBindings {} {
  571.     new -n {* Key Bindings *}
  572.     insertText [bindingList]
  573.  
  574.     global infoWindowsDirty
  575.     if {!$infoWindowsDirty} {setWinInfo dirty 0}
  576. }
  577.  
  578.  
  579. #================================================================================
  580.  
  581. proc printArray {arr} {
  582.     global $arr
  583.         foreach n [array names $arr] {
  584.         append text "$n '[set ${arr}($n)]'\r"
  585.     }
  586.     return [string trim $text "\r"]
  587. }
  588.  
  589. #================================================================================
  590.  
  591.  
  592. proc doATab {} {
  593.     global electricTab
  594.     if {!$electricTab || [regexp {[^ \t]} [getText [lineStart [getPos]] [getPos]]]} {
  595.         if {[getPos] != [selEnd]} {
  596.             replaceText [getPos] [selEnd] "\t"
  597.         } else {
  598.             insertText "\t"
  599.         }
  600.     } else {
  601.         indentLine
  602.     }
  603. }
  604.  
  605. #     set ptext [getText [lindex $lst 0] [nextLineStart [lindex $lst 0]]]
  606. #     regsub -all {[^(]} $ptext {} one
  607. #     regsub -all {[^)]} $ptext {} two
  608. #     if {[string length $one] > [string length $two]} {
  609. #         regexp {[^(]*\(} $ptext blah
  610. #         regsub -all {[^    ]} $blah { } lwhite
  611. #     } elseif {($nextC == "\{")} {
  612. #         append lwhite "\t"
  613. #     }
  614.  
  615. proc indentLine {} {
  616.     set beg [lineStart [getPos]]
  617.  
  618.     set lst [search -s -f 0 -r 1 -i 0 {^[ \t]*[^ \t\r]} [expr $beg-1]]
  619.     set lwhite [getText [lindex $lst 0] [expr [lindex $lst 1] - 1]]
  620.     set nextC [lookAt [expr [nextLineStart [lindex $lst 1]] - 2]]
  621.  
  622.     if {($nextC == "\{")} {
  623.         append lwhite "\t"
  624.     }
  625.     set text [getText $beg [nextLineStart $beg]]
  626.     regexp {^[ \t]*} $text white
  627.     set len [string length $white]
  628.     set nextC [lookAt [expr $beg + $len]]
  629.     if {$nextC == "\}"} {
  630.         set lwhite [string range $lwhite 0 [expr [string length $lwhite] - 2]]
  631.     }
  632.     
  633.     if {$white != $lwhite} {
  634.         replaceText $beg [expr $beg + $len] $lwhite
  635.     }
  636.     goto [expr $beg + [string length $lwhite]]
  637. }
  638.  
  639.  
  640. proc indentRegion {} {
  641.     set from [lindex [posToRowCol [getPos]] 0]
  642.     set to [lindex [posToRowCol [selEnd]] 0]
  643.     select [getPos]
  644.     while {$from <= $to} {
  645.         goto [rowColToPos $from 0]
  646.         indentLine
  647.         incr from
  648.     }
  649. }
  650.  
  651. #================================================================================
  652.  
  653. proc sPrompt {msg def} {
  654.     global useStatusBar
  655.     if {!$useStatusBar} {return [prompt $msg $def]}
  656.     if {[catch {statusPrompt "$msg ($def): "} ans]} {
  657.         error "cancel"
  658.     }
  659.     if {![string length $ans]} {return $def}
  660.     return $ans
  661. }
  662.  
  663. #================================================================================
  664. proc quoteChar {} {
  665.     message "Literal keystroke to be inserted:"
  666.     insertText [getChar]
  667. }
  668.